﻿/*
 * framemodbustcp.cpp
 *
 *  Created on: 2017年10月28日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_PROTOCOL DM_API_EXPORT

#include <dm/protocol/framemodbustcp.hpp>
#include <dm/bytes.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace protocol{

static const char* logModule = "CFrameModbusTcp.protocol.dm";

CFrameModbusTcp::CFrameModbusTcp():CFrameModbus(),
		m_transFlag(0),m_protocolFlag(0),m_unitFlag(1){
	log().debug( THISMODULE "创建对象");
}

CFrameModbusTcp::CFrameModbusTcp( const CFrameModbusTcp& frame ):
		CFrameModbus(frame),
		m_transFlag(frame.m_transFlag),m_protocolFlag(frame.m_protocolFlag),m_unitFlag(frame.m_unitFlag){
	log().debug( THISMODULE "构造对象");
}

CFrameModbusTcp& CFrameModbusTcp::operator =( const CFrameModbusTcp& frame ){
	m_transFlag = frame.m_transFlag;
	m_protocolFlag = frame.m_protocolFlag;
	m_unitFlag = frame.m_unitFlag;

	CFrameModbus::operator =(frame);

	return *this;
}

bool CFrameModbusTcp::encode( txbuf_t& buf )const{
	buf.push(dm::higByte_u16(m_transFlag));
	buf.push(dm::lowByte_u16(m_transFlag));
	buf.push(dm::higByte_u16(m_protocolFlag));
	buf.push(dm::lowByte_u16(m_protocolFlag));

	dm::uint16 len = 2+getLen();

	buf.push(dm::higByte_u16(len));
	buf.push(dm::lowByte_u16(len));

	buf.push(m_unitFlag);

	if( getFrameType()==FtUpErr )
		buf.push(getFunc()|0x80);
	else
		buf.push(getFunc());

	buf.push(getData(),getLen());

	return true;
}

bool CFrameModbusTcp::decode( const rxbuf_t& buf,const pos_t& end,pos_t& start,const CFrame* txFrame ){
	while( start!=end ){
		if( end - start<9 )
			return false;

		pos_t p = start;

		m_transFlag = dm::bytes2uint16(buf.dataAt(p+1),buf.dataAt(p));
		p += 2;
		m_protocolFlag = dm::bytes2uint16(buf.dataAt(p+1),buf.dataAt(p));
		p += 2;
		dm::uint16 len = dm::bytes2uint16(buf.dataAt(p+1),buf.dataAt(p));
		if( len>(MaxDataLen+2) ){
			++start;
			continue;
		}

		p += 2;

		m_unitFlag = buf.dataAt(p);

		++p;
		setFunc( EFunc(buf.dataAt(p)));

		++p;
		setLen(len - 2);
		if( end-p<getLen()  )
			return false;

		if( getFrameType()==FtDn ){
			// 当前处理子站接收主站的报文
			buf.getDataAndMovePos(m_data,m_len,p);
			start = p;
			return true;
		}else{
			// 当前处理主站接收子站报文
			if( m_fun&0x80 ){
				setUpErrorFrame();
				m_fun = EFunc(m_fun&0x7F);
			}else{
				setUpFrame();
			}

			if( txFrame==NULL ){
				log().warnning(THISMODULE "解析子站报文时，必须提供下发的报文作为参考");
				start = end;
				return false;
			}

			const CFrameModbusTcp* tf = dynamic_cast<const CFrameModbusTcp*>(txFrame);

			// 查找传输标志
			if( m_transFlag!=tf->m_transFlag ){
				++start;
				continue;
			}

			if( m_protocolFlag!=tf->m_protocolFlag ){
				++start;
				continue;
			}

			if( m_unitFlag!=tf->m_unitFlag ){
				++start;
				continue;
			}

			if( m_fun!=tf->m_fun ){
				++start;
				continue;
			}

			buf.getDataAndMovePos(m_data,m_len,p);
			start = p;
			return true;
		}
	}

	return false;
}

}
}


